package io.github.frailty9.crserver.config

import cn.dev33.satoken.stp.StpUtil
import cn.dev33.satoken.util.SaResult
import com.mybatisflex.core.paginate.Page
import io.github.frailty9.crserver.exception.DataInconsistencyException
import io.github.frailty9.crserver.model.BaseModel
import io.github.frailty9.crserver.model.toDto
import mu.KotlinLogging
import org.noear.solon.annotation.Component
import org.noear.solon.core.exception.StatusException
import org.noear.solon.core.handle.Context
import org.noear.solon.core.handle.Handler
import org.noear.solon.core.route.RouterInterceptor
import org.noear.solon.core.route.RouterInterceptorChain

@Component
class AppRouterInterceptor : RouterInterceptor {
    private val log = KotlinLogging.logger {}

    override fun doIntercept(
        ctx: Context,
        mainHandler: Handler?,
        chain: RouterInterceptorChain
    ) {
        try {
            chain.doIntercept(ctx, mainHandler)
        } catch (e: StatusException) {
            if (e.code == 404) {
                ctx.render(SaResult(404, "未找到资源", null))
            } else {
                renderDefaultError(ctx, e)
            }
        } catch (e: DataInconsistencyException) {
            e.printStackTrace()
            log.error("DataInconsistencyException: ${e.message}")
            ctx.render(SaResult(501, "数据异常，请与管理员联系", null))
        } catch (e: Throwable) {
            renderDefaultError(ctx, e)
        }
    }

    private fun renderDefaultError(ctx: Context, e: Throwable) {
        e.printStackTrace()
        log.error("RouterInterceptor error: ${e.message}")
        ctx.render(SaResult(500, "服务器内部错误，请与管理员联系", null))
    }

    override fun postResult(ctx: Context, result: Any?): Any? {
        // 集中处理系统数据擦除
        if (
            result != null &&
            result is SaResult &&
            result.code == 200 &&
            result.data != null &&
            StpUtil.isLogin() &&
            !StpUtil.getRoleList().contains("sys_admin")
        ) {
            when (val data = result.data) {
                // -------------- 常见 ------------------
                is BaseModel -> data.toDto()

                is Page<*> -> if(data.records.isNotEmpty() && data.records[0] is BaseModel)
                    data.records.map { (it as BaseModel).toDto() }

                is List<*> -> if (data.isNotEmpty() && data[0] is BaseModel)
                    data.map { (it as BaseModel).toDto() }

                is Array<*> -> if (data.isNotEmpty() && data[0] is BaseModel)
                    data.map { (it as BaseModel).toDto() }

                // -------------- 特殊 ------------------
            }
        }
        return super.postResult(ctx, result)
    }
}